﻿using System;
using System.Collections.Generic;
using System.Linq;


namespace CSharp.Libs.Misc
{
    public class MessageLogging : IDisposable
    {
        #region declarations
        private Dictionary<int, MessageItem> _dictMessages = new Dictionary<int, MessageItem>();
        
        private int _intMaxBufferSize = 500;
        private int _intID = 1;

        #region events
        public delegate void BeforeAddingMessageEventHandler(object sender, MessageLoggingEventArgs mlea);
        public event BeforeAddingMessageEventHandler BeforeAddingMessage;
        private void ThrowBeforeAddingMessageEvent(
            MessageLoggingEventArgs mlea)
        {
            if (BeforeAddingMessage != null)
            {
                BeforeAddingMessage(this, mlea);
            }
        }

        public delegate void AfterAddingMessageEventHandler(object sender, MessageLoggingEventArgs mlea);
        public event AfterAddingMessageEventHandler AfterAddingMessage;
        private void ThrowAfterAddingMessageEvent(
            MessageLoggingEventArgs mlea)
        {
            if (AfterAddingMessage != null)
            {
                AfterAddingMessage(this, mlea);
            }
        }

        public delegate void BeforeDeletingMessageEventHandler(object sender, MessageLoggingEventArgs mlea);
        public event BeforeDeletingMessageEventHandler BeforeDeletingMessage;
        private void ThrowBeforeDeletingMessageEvent(
            MessageLoggingEventArgs mlea)
        {
            if (BeforeDeletingMessage != null)
            {
                BeforeDeletingMessage(this, mlea);
            }
        }

        public delegate void AfterDeletingMessageEventHandler(object sender, MessageLoggingEventArgs mlea);
        public event AfterDeletingMessageEventHandler AfterDeletingMessage;
        private void ThrowAfterDeletingMessageEvent(
            MessageLoggingEventArgs mlea)
        {
            if (AfterDeletingMessage != null)
            {
                AfterDeletingMessage(this, mlea);
            }
        }
        #endregion
        #endregion



        #region constructor / terminator
        public MessageLogging()
        {
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool disposing)
        {
            if(disposing)
            {
                // get rid of managed resources
                //_EC = null;
                _dictMessages = null;
            }
            // get rid of unmanaged resources
        }

        ~MessageLogging()
        {
            Dispose(false);
        }
        #endregion



        #region private functions
        private MessageItem _addMessageItem(
            MessageItem MI)
        {
            //Check if key already exists
            if (_dictMessages.ContainsKey(MI.Id))
            {
                //_EC.AddException(new Exception("Key already exists!"), this.ToString(), _EC.Tools.GetCurrentMethodName());
                return MI;
            }

            //Add MessageItem
            ThrowBeforeAddingMessageEvent(new MessageLoggingEventArgs(DateTime.Now, MI));
            _dictMessages.Add(MI.Id, MI);
            ThrowAfterAddingMessageEvent(new MessageLoggingEventArgs(DateTime.Now, MI));

            //check count and remove oldest entries
            if (_dictMessages.Count > _intMaxBufferSize)
            {
                while (_dictMessages.Count > _intMaxBufferSize)
                {
                    int intMinKey = _dictMessages.Min(l => l.Key);
                    MessageItem miDelete = _dictMessages[intMinKey];

                    ThrowBeforeDeletingMessageEvent(new MessageLoggingEventArgs(DateTime.Now, miDelete));
                    _dictMessages.Remove(intMinKey);
                    ThrowAfterDeletingMessageEvent(new MessageLoggingEventArgs(DateTime.Now, miDelete));

                    miDelete = null;
                }
            }

            return MI;
        }
        #endregion



        #region interface
        #region properties
        public Dictionary<int, MessageItem> Messages { get { return _dictMessages; } }

        public int MaxBufferSize
        {
            get { return _intMaxBufferSize; }
            set
            {
                if (value != _intMaxBufferSize)
                {
                    _intMaxBufferSize = value;
                }
            }
        }
        #endregion

        #region methods
        #region adding messages
        public void AddMessage(
            MessageItem MI)
        {
            _addMessageItem(MI);
        }

        public MessageItem AddMessage(
            string strText)
        {
            return _addMessageItem(new MessageItem(_intID++, MessageType.Information, strText));
        }

        public MessageItem AddMessage(
            MessageType mtType,
            string strText)
        {
            return _addMessageItem(new MessageItem(_intID++, mtType, strText));
        }

        public MessageItem AddMessage(
            MessageType mtType,
            DateTime dtOccurred,
            string strText)
        {
            return _addMessageItem(new MessageItem(_intID++, mtType, dtOccurred, strText));
        }

        public MessageItem AddMessage(
            int intID,
            MessageType mtType,
            DateTime dtOccurred,
            string strText)
        {
            return _addMessageItem(new MessageItem(intID, mtType, dtOccurred, strText));
        }
        #endregion
        #endregion
        #endregion
    }
}
